﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ReAnimation.MVP.ViewInterfaces;
using ReAnimation.MVP.Models.Interfaces;
using ReAnimation.Domain;
using ReAnimation.Helpers.DynamicProxy;
using Sharp3D.Math.Core;
using GLWrap.MathExt;
using GLWrap;

namespace ReAnimation.MVP.Views
{
    public partial class MoleculeRotationAndTranslateView : BaseUserControlView,IMoleculeRotationAndTranslateView
    {
        private ReAnimation.Helpers.DynamicProxy.Action handler;
        private IMainModel _mainModel;
        private IGlSceneManager _glSceneManager;
        private Molecule _mol;

        public MoleculeRotationAndTranslateView(IMainModel mainModel,
            IGlSceneManager glSceneManager)
        {
            handler = () => { UpdateControls(); };
            _glSceneManager = glSceneManager;
            _mainModel = mainModel;
            InitializeComponent();

            UpdateControls();

            _mol = _mainModel.CurrentMolecule;
            Subscribe();
            
            _mainModel.CurrentMoleculeChanged += (s, o) => 
            {
                Unsubscribe();
                _mol = _mainModel.CurrentMolecule;
                Subscribe();
                UpdateControls(); 
            };

        }

        private void UpdateControls()
        {
            if (_mol == null)
            {
                SetDefaults();
                return;
            }
            QuaternionF q = _mol.TransformMatrix.GetQuaternion();
            Vector3F axis = new Vector3F(0,0,0);
            float angle = 0;
            q.GetAxisAndAngle(ref axis,ref angle);
            axisXTextBox.Value = axis.X;
            axisYTextBox.Value = axis.Y;
            axisZTextBox.Value = axis.Z;
            rotationAngleTextBox.Value = angle.RadiansToDegrees();

            Vector3F tv = new Vector3F(
                _mol.TransformMatrix.M14,
                _mol.TransformMatrix.M24,
                _mol.TransformMatrix.M34
                );
            translateXTextBox.Value = tv.X;
            translateYTextBox.Value = tv.Y;
            translateZTextBox.Value = tv.Z;
        }

        private void SetDefaults()
        {
            axisXTextBox.Value =
                axisYTextBox.Value =
                axisZTextBox.Value =
                rotationAngleTextBox.Value =
                translateXTextBox.Value =
                translateYTextBox.Value =
                translateZTextBox.Value = 0;
        }

        private void Subscribe()
        {
            if (_mol == null) return;
            EventsSource.EditSubscriptionsFor(_mol).AfterPropertySet<Matrix4F>(()=>_mol.TransformMatrix)
                .Handler(handler);
        }

        private void Unsubscribe()
        {
            if (_mol == null) return;
            EventsSource.EditSubscriptionsFor(_mol).RemoveHandler(handler);
        }

        private void applyBtn_Click(object sender, EventArgs e)
        {
            Vector3F axis = new Vector3F(
                axisXTextBox.Value,
                axisYTextBox.Value,
                axisZTextBox.Value
                );
            float angle = rotationAngleTextBox.Value;
            Vector3F translateVector = new Vector3F(
                translateXTextBox.Value,
                translateYTextBox.Value,
                translateZTextBox.Value
                );

            QuaternionF q = QuaternionFExtension.CreateWithAxisAndAngle(axis, angle);
            Matrix4F mat = q.GetRotationMatrix();

            mat.M14 = translateVector.X;
            mat.M24 = translateVector.Y;
            mat.M34 = translateVector.Z;

            _mol.TransformMatrix = mat;

            _glSceneManager.Refresh();
        }

        private void defaultBtn_Click(object sender, EventArgs e)
        {
            SetDefaults();
        }
    }
}
